xl: detect pci-insert-failed dm status on pci-passthrough
authorGianni Tedesco <gianni.tedesco@citrix.com>
Wed, 4 Aug 2010 13:43:46 +0000 (14:43 +0100)
committerGianni Tedesco <gianni.tedesco@citrix.com>
Wed, 4 Aug 2010 13:43:46 +0000 (14:43 +0100)
NOTE: This functionality depends on a corresponding qemu-dm patch to work as
expected. Should be safe to use with an un-patched qemu-dm as before.

libxl_wait_for_device_model can only wait for one status value, re-work the
API so that a callback function can chose between several different possible
status values for qemu-dm and fix up all callers appropriately.

In the case of PCI device insert we succeed if qemu-dm reports
"pci-device-inserted" and error out instead of hanging forever if it fails
since qemu-dm now reports a status of "pci-insert-failed".

Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl_device.c
tools/libxl/libxl_internal.h
tools/libxl/libxl_pci.c

index 0a2dbf89e938ad170f4874bd4997136b3b4c5675..b34806411ec0c1a2b5ea1b02811917d783e8db0e 100644 (file)
@@ -1420,12 +1420,12 @@ int libxl_detach_device_model(libxl_ctx *ctx,
 int libxl_confirm_device_model_startup(libxl_ctx *ctx,
                                        libxl_device_model_starting *starting)
 {
-    int problem = libxl_wait_for_device_model(ctx, starting->domid, "running",
-                                              libxl_spawn_check,
-                                              starting->for_spawn);
-    int detach = libxl_detach_device_model(ctx, starting);
+    int problem = libxl_wait_for_device_model(ctx, starting->domid, "running", NULL, NULL);
+    int detach;
+    if ( !problem )
+        problem = libxl_spawn_check(ctx, starting->for_spawn);
+    detach = libxl_detach_device_model(ctx, starting);
     return problem ? problem : detach;
-    return 0;
 }
 
 
index c59c631457bbdf5ad886b1c21f769d333877df26..c81b85475bc126eadfbcb5f2c64ce687bcfadca5 100644 (file)
@@ -380,6 +380,8 @@ int libxl_device_del(libxl_ctx *ctx, libxl_device *dev, int wait)
 int libxl_wait_for_device_model(libxl_ctx *ctx,
                                 uint32_t domid, char *state,
                                 int (*check_callback)(libxl_ctx *ctx,
+                                                      uint32_t domid,
+                                                      const char *state,
                                                       void *userdata),
                                 void *check_callback_userdata)
 {
@@ -402,18 +404,24 @@ int libxl_wait_for_device_model(libxl_ctx *ctx,
     nfds = xs_fileno(xsh) + 1;
     while (rc > 0 || (!rc && tv.tv_sec > 0)) {
         p = xs_read(xsh, XBT_NULL, path, &len);
-        if (p && (!state || !strcmp(state, p))) {
-            free(p);
-            xs_unwatch(xsh, path, path);
-            xs_daemon_close(xsh);
-            if (check_callback) {
-                rc = check_callback(ctx, check_callback_userdata);
-                if (rc) return rc;
-            }
-            return 0;
+        if ( NULL == p )
+            goto again;
+
+        if ( NULL != state && strcmp(p, state) )
+            goto again;
+
+        if ( NULL != check_callback ) {
+            rc = (*check_callback)(ctx, domid, p, check_callback_userdata);
+            if ( rc > 0 )
+                goto again;
         }
+
         free(p);
+        xs_unwatch(xsh, path, path);
+        xs_daemon_close(xsh);
+        return rc;
 again:
+        free(p);
         FD_ZERO(&rfds);
         FD_SET(xs_fileno(xsh), &rfds);
         rc = select(nfds, &rfds, NULL, NULL, &tv);
index 36a2829f97e671e16b04acfe8f429350e41c8bdb..3f0454468ae0dff5e98b2a38a481d860ce17ccf5 100644 (file)
@@ -162,6 +162,8 @@ int libxl_devices_destroy(libxl_ctx *ctx, uint32_t domid, int force);
 int libxl_wait_for_device_model(libxl_ctx *ctx,
                                 uint32_t domid, char *state,
                                 int (*check_callback)(libxl_ctx *ctx,
+                                                      uint32_t domid,
+                                                      const char *state,
                                                       void *userdata),
                                 void *check_callback_userdata);
 int libxl_wait_for_backend(libxl_ctx *ctx, char *be_path, char *state);
index 20f4a00218ffcd18868294a8180ace55877570d6..c4dc0e41466c0fdafeea2060e4a5b0334240ba16 100644 (file)
@@ -531,6 +531,20 @@ int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, in
     return 0;
 }
 
+static int pci_ins_check(libxl_ctx *ctx, uint32_t domid, const char *state, void *priv)
+{
+    char *orig_state = priv;
+
+    if ( !strcmp(state, "pci-insert-failed") )
+        return -1;
+    if ( !strcmp(state, "pci-inserted") )
+        return 0;
+    if ( !strcmp(state, orig_state) )
+        return 1;
+
+    return 1;
+}
 static int do_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
 {
     char *path;
@@ -553,13 +567,17 @@ static int do_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
                            pcidev->bus, pcidev->dev, pcidev->func);
         path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
         xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
-        if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, NULL) < 0)
-            XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
+        rc = libxl_wait_for_device_model(ctx, domid, NULL, pci_ins_check, state);
         path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
         vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
-        sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
         path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
+        if ( rc < 0 )
+            XL_LOG(ctx, XL_LOG_ERROR, "qemu refused to add device: %s", vdevfn);
+        else if ( sscanf(vdevfn, "0x%x", &pcidev->vdevfn) != 1 )
+            rc = -1;
         xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
+        if ( rc )
+            return ERROR_FAIL;
     } else {
         char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
                                          pcidev->bus, pcidev->dev, pcidev->func);